﻿using Compass.Wasm.Shared.Wms;
using Compass.Wpf.ApiServices;
using Compass.Wpf.ApiServices.Wms;
using Compass.Wpf.Views.Wms;

namespace Compass.Wpf.ViewModels.Wms;

public class CargoesInquiryViewModel : NavigationViewModel
{
    #region ctor
    private readonly ICargoService _cargoService;
    private readonly IInventoryService _inventoryService;
    private readonly IStockInService _stockInService;
    private readonly IStockOutService _stockOutService;
    private readonly IPreferenceService _preferenceService;
    public CargoesInquiryViewModel(IContainerProvider provider) : base(provider)
    {
        _cargoService = provider.Resolve<ICargoService>();
        _inventoryService = provider.Resolve<IInventoryService>();
        _stockInService = provider.Resolve<IStockInService>();
        _stockOutService = provider.Resolve<IStockOutService>();
        _preferenceService = provider.Resolve<IPreferenceService>();
        CargoDto=new CargoDto();
        InventoryDto=new InventoryDto();
        StockInDto=new StockInDto();
        StockOutDto=new StockOutDto();


        ExecuteCommand=new DelegateCommand<string>(Execute);
        AddInventoryCommand = new DelegateCommand<CargoDto>(AddInventory);
        AddStockInCommand = new DelegateCommand<CargoDto>(AddStockIn);
        AddStockOutCommand = new DelegateCommand<CargoDto>(AddStockOut);
        CalculateDiffCommand = new DelegateCommand(CalculateDiff);
        SaveInventoryCommand = new DelegateCommand(SaveInventory);
        SaveStockInCommand = new DelegateCommand(SaveStockIn);
        SaveStockOutCommand = new DelegateCommand(SaveStockOut);
        UpdateRoles = "admin,whse";
        RightDrawerTitle = "库存操作";
    }

    private string updateRoles;
    public string UpdateRoles
    {
        get => updateRoles;
        set { updateRoles = value; RaisePropertyChanged(); }
    }
    public DelegateCommand<string> ExecuteCommand { get; }
    public DelegateCommand<CargoDto> AddInventoryCommand { get; }
    public DelegateCommand<CargoDto> AddStockInCommand { get; }
    public DelegateCommand<CargoDto> AddStockOutCommand { get; }
    public DelegateCommand CalculateDiffCommand { get; }
    public DelegateCommand SaveInventoryCommand { get; }
    public DelegateCommand SaveStockInCommand { get; }
    public DelegateCommand SaveStockOutCommand { get; }
    #endregion

    #region 右侧展开栏属性
    private bool isRightDrawerOpen;
    /// <summary>
    /// 右侧窗口是否展开
    /// </summary>
    public bool IsRightDrawerOpen
    {
        get => isRightDrawerOpen;
        set { isRightDrawerOpen = value; RaisePropertyChanged(); }
    }
    private string rightDrawerTitle = null!;
    public string RightDrawerTitle
    {
        get => rightDrawerTitle;
        set { rightDrawerTitle = value; RaisePropertyChanged(); }
    }

    private bool canSelectCargo;
    public bool CanSelectCargo
    {
        get => canSelectCargo;
        set { canSelectCargo = value; RaisePropertyChanged(); }
    }
    #endregion

    #region 属性
    private Warehouse_e warehouse;
    public Warehouse_e Warehouse
    {
        get => warehouse;
        set
        {
            SetProperty(ref warehouse, value);
            SearchAll = false;
        }
    }

    private string[] warehouses = null!;
    public string[] Warehouses
    {
        get => warehouses;
        set { warehouses = value; RaisePropertyChanged(); }
    }

    private Area_e area;
    public Area_e Area
    {
        get => area;
        set
        {
            SetProperty(ref area, value);
            SearchAll = false;
        }
    }

    private string[] areas = null!;
    public string[] Areas
    {
        get => areas;
        set { areas = value; RaisePropertyChanged(); }
    }

    private string column;
    public string Column
    {
        get => column;
        set
        {
            SetProperty(ref column, value);
            SearchAll = false;
        }
    }

    private string[] columns = null!;
    public string[] Columns
    {
        get => columns;
        set { columns = value; RaisePropertyChanged(); }
    }

    private string row;
    public string Row
    {
        get => row;
        set
        {
            SetProperty(ref row, value);
            SearchAll = false;
        }
    }

    private string[] rows = null!;
    public string[] Rows
    {
        get => rows;
        set { rows = value; RaisePropertyChanged(); }
    }
    private string search;
    /// <summary>
    /// 搜索条件属性
    /// </summary>
    public string Search
    {
        get => search;
        set
        {
            search = value;
            RaisePropertyChanged();
            Filter();
        }
    }
    private bool searchAll;
    /// <summary>
    /// 全范围搜索
    /// </summary>
    public bool SearchAll
    {
        get => searchAll;
        set
        {
            SetProperty(ref searchAll, value);
            GetDataAsync();
        }
    }
    private bool shortAge;
    public bool ShortAge
    {
        get => shortAge;
        set
        {
            SetProperty(ref shortAge, value);
            Filter();
        }
    }
    private CargoDto cargoDto;
    public CargoDto CargoDto
    {
        get => cargoDto;
        set { cargoDto = value; RaisePropertyChanged(); }
    }
    public ObservableRangeCollection<CargoDto> CargoDtos { get; } = new();
    public ObservableRangeCollection<CargoDto> FilterCargoDtos { get; } = new();



    #endregion

    #region 导航
    private void Navigate(string target, NavigationParameters? param = null)
    {
        RegionManager.Regions[PrismManager.MainViewRegionName].RequestNavigate(target, back =>
        {
            Journal = back.Context.NavigationService.Journal;
        }, param);
    }
    private void Execute(string obj)
    {
        switch (obj)
        {
            case "Inventories":
                Navigate(nameof(InventoriesView));
                break;
            case "StockIns":
                Navigate(nameof(StockInsView));
                break;
            case "StockOuts":
                Navigate(nameof(StockOutsView));
                break;
        }
    }
    #endregion


    #region 三种操作需要的属性
    private bool selInventory;
    public bool SelInventory
    {
        get => selInventory;
        set { selInventory = value; RaisePropertyChanged(); }
    }
    private bool selStockIn;
    public bool SelStockIn
    {
        get => selStockIn;
        set { selStockIn = value; RaisePropertyChanged(); }
    }
    private bool selStockOut;
    public bool SelStockOut
    {
        get => selStockOut;
        set { selStockOut = value; RaisePropertyChanged(); }
    }
    private InventoryDto inventoryDto;
    public InventoryDto InventoryDto
    {
        get => inventoryDto;
        set { inventoryDto = value; RaisePropertyChanged(); }
    }
    private StockInDto stockInDto;
    public StockInDto StockInDto
    {
        get => stockInDto;
        set { stockInDto = value; RaisePropertyChanged(); }
    }
    private StockOutDto stockOutDto;
    public StockOutDto StockOutDto
    {
        get => stockOutDto;
        set { stockOutDto = value; RaisePropertyChanged(); }
    }

    private string[] stations = null!;
    public string[] Stations
    {
        get => stations;
        set { stations = value; RaisePropertyChanged(); }
    }
    #endregion

    #region 盘存，入库，出库操作
    private void AddInventory(CargoDto obj)
    {
        CargoDto=obj;
        SelInventory=true;
        SelStockIn = false;
        SelStockOut=false;
        IsRightDrawerOpen = true;

        InventoryDto = new InventoryDto
        {
            CargoId = CargoDto.Id!.Value,
            Operator = _preferenceService.Get(Consts.UserName),
            OperatorId = Guid.Parse(_preferenceService.Get(Consts.UserId)),
            CountTime = DateTime.Now
        };
    }


    private void AddStockIn(CargoDto obj)
    {
        CargoDto=obj;
        SelInventory =false;
        SelStockIn = true;
        SelStockOut=false;
        IsRightDrawerOpen = true;
        StockInDto = new StockInDto
        {
            CargoId = CargoDto.Id!.Value,
            Operator = _preferenceService.Get(Consts.UserName),
            OperatorId = Guid.Parse(_preferenceService.Get(Consts.UserId)),
            InTime = DateTime.Now
        };
    }

    private void AddStockOut(CargoDto obj)
    {
        CargoDto=obj;
        SelInventory=false;
        SelStockIn = false;
        SelStockOut=true;
        IsRightDrawerOpen = true;
        StockOutDto = new StockOutDto
        {
            CargoId = CargoDto.Id!.Value,
            Operator = _preferenceService.Get(Consts.UserName),
            OperatorId = Guid.Parse(_preferenceService.Get(Consts.UserId)),
            OutTime = DateTime.Now
        };
    }

    private void CalculateDiff()
    {
        if (InventoryDto.Quantity <= 0)
        {
            //发送提示
            Aggregator.SendMessage("盘存数量不能小于或等于0");
            return;
        }
        //大于0，盘盈，小于0，盘亏
        InventoryDto.Diff = InventoryDto.Quantity - CargoDto.Inventory;
    }

    private async void SaveInventory()
    {
        //数据验证
        if (InventoryDto.CargoId==Guid.Empty)
        {
            //发送提示
            Aggregator.SendMessage("物料不能为空，请选择物料");
            return;
        }
        if (InventoryDto.Quantity==0)
        {
            //发送提示
            Aggregator.SendMessage("物料数量不能为0，请选择物料");
            return;
        }
        if (InventoryDto.operatorId==Guid.Empty)
        {
            //发送提示
            Aggregator.SendMessage("没有登录？");
            return;
        }

        try
        {
            await _inventoryService.AddAsync(InventoryDto);
            Aggregator.SendMessage($"物料盘存记录：{CargoDto.MtlNumber},{CargoDto.Description}, 数量:{InventoryDto.Quantity} 添加成功！");
            InventoryDto.Id=Guid.Empty;

            IsRightDrawerOpen = false;
            GetDataAsync();
        }
        catch (Exception e)
        {
            //发送错误报告
            Aggregator.SendMessage(e.Message);
        }

    }

    private async Task UpdatePrice()
    {
        //如果采购价格是0，则使用Cargo的LastPrice
        //如果采购价格不是0，则更新Cargo的LastPrice
        if (StockInDto.Price.Equals(0))
        {
            StockInDto.Price = CargoDto.LastPrice;
        }
        else
        {
            var oneYearStockIns = (await _stockInService.GetFromLastByCargoAsync(cargoDto.Id.Value,
                new DateTime(DateTime.Now.Year - 1, DateTime.Now.Month, DateTime.Now.Day))).Result;
            CargoDto.LastPrice = StockInDto.Price;
            CargoDto.AvgPrice = oneYearStockIns.Average(x => x.Price);
            await _cargoService.UpdateAsync(CargoDto.Id.Value, CargoDto);
        }
    }

    private async void SaveStockIn()
    {
        //数据验证
        if (StockInDto.CargoId==Guid.Empty)
        {
            //发送提示
            Aggregator.SendMessage("物料不能为空，请选择物料");
            return;
        }
        if (StockInDto.Quantity==0)
        {
            //发送提示
            Aggregator.SendMessage("物料数量不能为0，请选择物料");
            return;
        }
        if (StockInDto.operatorId==Guid.Empty)
        {
            //发送提示
            Aggregator.SendMessage("没有登录？");
            return;
        }
        //在途为0则不判断，在途不为0则判断本次入库数量，不能大于在途
        if (StockInDto.TransitQuantity != 0 && StockInDto.TempQuantity>StockInDto.TransitQuantity)
        {
            //发送提示
            Aggregator.SendMessage($"本次入库数量{StockInDto.TempQuantity}不能大于在途数量{StockInDto.TransitQuantity}!");
            return;
        }

        if (StockInDto.TransitQuantity != 0)
        {
            StockInDto.TransitQuantity -= StockInDto.TempQuantity;//扣减在途
        }

        StockInDto.Quantity += StockInDto.TempQuantity;//增加入库

        try
        {

            await UpdatePrice();
            await _stockInService.AddAsync(StockInDto);
            Aggregator.SendMessage($"物料入库记录：{CargoDto.MtlNumber},{CargoDto.Description}, 数量:{StockInDto.Quantity} 添加成功！");
            StockInDto.Id=Guid.Empty;

            IsRightDrawerOpen = false;
            GetDataAsync();
        }
        catch (Exception e)
        {
            //发送错误报告
            Aggregator.SendMessage(e.Message);
        }
    }

    private async void SaveStockOut()
    {
        //数据验证
        if (StockOutDto.CargoId==Guid.Empty)
        {
            //发送提示
            Aggregator.SendMessage("物料不能为空，请选择物料");
            return;
        }
        if (StockOutDto.Quantity==0)
        {
            //发送提示
            Aggregator.SendMessage("物料数量不能为0，请选择物料");
            return;
        }
        if (StockOutDto.operatorId==Guid.Empty)
        {
            //发送提示
            Aggregator.SendMessage("没有登录？");
            return;
        }
        //待领料为0则不判断，待领料不为0则判断本次出库数量，不能大于待领料
        if (StockOutDto.TransitQuantity != 0 && StockOutDto.TempQuantity>StockOutDto.TransitQuantity)
        {
            //发送提示
            Aggregator.SendMessage($"本次出库数量{StockOutDto.TempQuantity}不能大于待领料数量{StockOutDto.TransitQuantity}!");
            return;
        }
        if (StockOutDto.TransitQuantity != 0)
        {
            StockOutDto.TransitQuantity -= StockOutDto.TempQuantity;//扣减待领料
        }
        StockOutDto.Quantity += StockOutDto.TempQuantity;//增加出库

        try
        {

            await _stockOutService.AddAsync(StockOutDto);
            Aggregator.SendMessage($"物料出库记录：{CargoDto.MtlNumber},{CargoDto.Description}, 数量:{StockOutDto.Quantity} 添加成功！");
            StockOutDto.Id=Guid.Empty;
            IsRightDrawerOpen = false;
            GetDataAsync();
        }
        catch (Exception e)
        {
            //发送错误报告
            Aggregator.SendMessage(e.Message);
        }
    }


    #endregion
    
    #region 筛选
    private void Filter()
    {
        FilterCargoDtos.ReplaceRange(
            CargoDtos.Where(x =>
                (!ShortAge||x.ShortAge)&&(
                string.IsNullOrEmpty(Search)||
                x.MtlNumber.Contains(Search, StringComparison.OrdinalIgnoreCase)||
                (!string.IsNullOrEmpty(x.Description)&&x.Description!.Contains(Search, StringComparison.OrdinalIgnoreCase)) ||
                (!string.IsNullOrEmpty(x.EnDescription)&&x.EnDescription!.Contains(Search, StringComparison.OrdinalIgnoreCase)) ||
                x.Group.ToString().Contains(Search, StringComparison.OrdinalIgnoreCase)||
                (!string.IsNullOrEmpty(x.Location)&&x.Location!.Contains(Search, StringComparison.OrdinalIgnoreCase)) ||
                (!string.IsNullOrEmpty(x.Vendors)&&x.Vendors!.Contains(Search, StringComparison.OrdinalIgnoreCase)) ||
                (!string.IsNullOrEmpty(x.Remarks)&&x.Remarks!.Contains(Search, StringComparison.OrdinalIgnoreCase))
                )));
        //有的时候Remarks是null，导致调用Contains报错
    }
    #endregion

    #region 导航和初始化
    private void GetEnumNames()
    {
        //初始化一些枚举值
        Warehouses=Enum.GetNames(typeof(Warehouse_e));
        Areas=Enum.GetNames(typeof(Area_e));
        Columns = Enumerable.Range(1, 9).ToArray().ToList().ConvertAll<string>(x => x.ToString()).ToArray();
        Rows = Enumerable.Range(1, 9).ToArray().ToList().ConvertAll<string>(x => x.ToString()).ToArray();
        Column = Columns[0];
        Row = Rows[0];
        Stations = Enum.GetNames(typeof(Station_e));
    }



    private async void GetDataAsync()
    {
        if (SearchAll)
        {
            var result = await _cargoService.GetAllWithInventoryAsync();
            if (result.Status)
            {
                CargoDtos.ReplaceRange(result.Result);
            }
        }
        else
        {
            var ranks = $"{Column}-{Row}-";
            var result = await _cargoService.GetAllByAreaWithInventoryAsync(Warehouse, Area, ranks);
            if (result.Status)
            {
                CargoDtos.ReplaceRange(result.Result);
            }
        }
        Filter();
    }

    public override void OnNavigatedTo(NavigationContext navigationContext)
    {
        base.OnNavigatedTo(navigationContext);

        GetEnumNames();
        GetDataAsync();
    }
    #endregion

}